package com.wh.message.file.service.impl;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.PutObjectResult;
import com.wh.common.util.Result;
import com.wh.message.file.pojo.FileInUtil;
import com.wh.message.file.pojo.ModuleTypeEnum;
import com.wh.message.file.pojo.OSSUpFileIn;
import com.wh.message.file.pojo.OSSUpFileOut;
import com.wh.message.file.service.IFileService;
import com.wh.msg.ResultCode;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 公共附件上传
 * @author 谢泽鹏
 * @version V1.0
 * @Package com.wh.message.mq.service.impl
 * @date 2014年10月8日 下午4:02:14
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2018
 */
@Service
public class IFileServiceImpl implements IFileService {

    private static final Logger logger = LoggerFactory.getLogger(IFileServiceImpl.class);

    private static final FastDateFormat DATE_FORMAT = FastDateFormat.getInstance("yyyy/MM/dd");

    private static final FastDateFormat DATE_FORMAT_ = FastDateFormat.getInstance("yyyyMMdd");

    /**
     * 上传域名
     */
    @Value("#{settings['aliyun_endpoint']}")
    private String endpoint;

    /**
     * 秘钥ID
     */
    @Value("#{settings['aliyun_accesskeyid']}")
    private String accessKeyId;

    /**
     * 秘钥值
     */
    @Value("#{settings['aliyun_accesskeysecret']}")
    private String accessKeySecret;

    /**
     * 存储空间名称
     */
    @Value("#{settings['aliyun_bucketname']}")
    private String bucketName;

    /**
     * 下载地址
     */
    @Value("#{settings['aliyun_fileUrl']}")
    private String aliyunFileUrl;


    /**
     * 使用流上传附件
     * @param fileInUtil  文件信息
     * @param ossUpFileIn 上传入参
     */
    @Override
    public Result uploadFile(FileInUtil fileInUtil, OSSUpFileIn ossUpFileIn) {
        List<FileInUtil> fileInUtils = new ArrayList<>();
        fileInUtils.add(fileInUtil);
        return uploadFile(fileInUtils, ossUpFileIn);
    }

    /**
     * 批量使用流上传附件
     * @param fileInUtils 文件信息
     * @param ossUpFileIn 上传文件入参
     */
    @Override
    public Result uploadFile(List<FileInUtil> fileInUtils, OSSUpFileIn ossUpFileIn) {
        logger.info("uploadFile附件上传-->>开始");
        logger.info("uploadFile附件上传fileInUtils = {}", JSONArray.fromObject(fileInUtils));
        logger.info("uploadFile附件上传OSSUpFileIn = {}", JSONObject.fromObject(ossUpFileIn));
        Result result = new Result();
        try {
            result.setResCode(ResultCode.RES_OK);
            long start = System.currentTimeMillis();
            logger.info("uploadFile附件上传开始..." + start);
            if (fileInUtils != null && fileInUtils.size() > 0 && StringUtils.isNotBlank(ossUpFileIn.getBusinessId()) && StringUtils.isNotBlank(ossUpFileIn.getPlatType()) && ossUpFileIn.getTypeEnum() != null) {
                OSSClient ossClient = null;
                List<OSSUpFileOut> ossUpFileOuts = new ArrayList<>();
                OSSUpFileOut ossUpFileOut;
                ossClient = getOSSClient();
                byte[] bytes;
                for (FileInUtil file : fileInUtils) {
                    if (file != null) {
                        bytes = file.getData();
                        //附件原名称
                        String fileName = file.getFileName();
                        //附件原名称
                        if (StringUtils.isNotBlank(fileName) && null != bytes) {
                            //公共附件上传方法
                            ossUpFileOut = upload(ossUpFileIn, bytes, fileName, ossClient);
                            ossUpFileOuts.add(ossUpFileOut);
                        }
                    }
                }
                result.setResult(ossUpFileOuts.size() > 1 ? ossUpFileOuts : ossUpFileOuts.get(0));
                if (null != ossClient ) {
                    ossClient.shutdown();
                }
            } else {
                logger.info("uploadFile附件上传-->>参数格式错误");
                result.setResCode(ResultCode.RES_2001);
            }
            logger.info("uploadFile附件上传成功, 上传耗时：{}毫秒", System.currentTimeMillis() - start);
        }catch (Exception e){
            logger.error("uploadFile附件上传错误, 出现异常msg = {}", e.getMessage());
            e.printStackTrace();
            result.setResCode(ResultCode.RES_ERR);
        }
            logger.info("uploadFile附件上传-->>结束");
            return result;
    }


    /**
     * 公共附件上传方法
     * @param ossUpFileIn    上传文件入参
     * @param bytes          上传文件byte流
     * @param sourceFileName 源文件名称
     * @param client
     * @return
     */
    private OSSUpFileOut upload(OSSUpFileIn ossUpFileIn, byte[] bytes, String sourceFileName, OSSClient client) {
        OSSUpFileOut ossUpFileOut = new OSSUpFileOut();
        //生成附件uuid
        String uuid = getUUID();
        //生成附件名称
        String fileName = DATE_FORMAT_.format(new Date()) + getRandomName(uuid) + sourceFileName.substring(sourceFileName.lastIndexOf("."));
        //附件模块类型枚举值
        String type = null;
        try {
            type = ossUpFileIn.getTypeEnum().getType();
        } catch (Exception e) {
            logger.warn("枚举类型出错，手动设置为默认值.");
            type = ModuleTypeEnum.OTHER.getType();
        }
        //上传路径
        String path = type + "/" + DATE_FORMAT.format(new Date()) + "/" + fileName;
        logger.info("上传附件名称：{}", fileName);
        logger.info("上传附件路径：{}", aliyunFileUrl + "/" + path);
        PutObjectResult putObjectResult = client.putObject(bucketName, path, new ByteArrayInputStream(bytes));
        logger.info("附件上传结果：{}", putObjectResult.getETag());
        ossUpFileOut.setFileId(uuid);
        ossUpFileOut.setUrl(aliyunFileUrl + "/" + path);
        return ossUpFileOut;
    }


    /**
     * 获取OSSClient
     * @return
     */
    private OSSClient getOSSClient() {
        OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        if (!client.doesBucketExist(bucketName)) {
            client.createBucket(bucketName);
        }
        return client;
    }


    /**
     * 获取随机名字
     * @param uuid
     * @return
     */
    private String getRandomName(String uuid) {
        StringBuffer fileName = new StringBuffer();
        fileName.append(uuid.toUpperCase().substring(0, 5));
        fileName.append(ThreadLocalRandom.current().nextInt(10000, 99999));
        return fileName.toString();
    }

    /**
     * 获取uuid
     */
    private String getUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }
}
